package com.niiwoo.civet.trade.service.local.statisticsinfo;

import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.trade.dao.entity.StatisticsInfo;
import com.niiwoo.civet.trade.dao.mapper.ProjectMapperExt;
import com.niiwoo.civet.trade.dao.mapper.StatisticsInfoMapperExt;
import com.niiwoo.civet.trade.dto.response.statisticsinfo.StatisticsInfoResponseDTO;
import com.niiwoo.civet.trade.enums.ProjectStatusEnum;
import com.niiwoo.civet.trade.enums.StatisticsTypeEnum;
import com.niiwoo.civet.trade.service.local.configure.TradeConfigLocalService;
import com.niiwoo.tripod.base.utils.DateUtils;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.FastDateFormat;
import org.joda.time.Duration;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author: wuke
 * @Description: 数据统计相关
 * @Date: Created in 17:47 2017/12/29
 */
@Slf4j
@Service
public class StatisticsInfoService {
    @Autowired
    private StatisticsInfoMapperExt statisticsInfoMapper;
    @Autowired
    private ProjectMapperExt projectMapperExt;
    @Autowired
    RedisTemplate<String, String> redisTemplate;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private TradeConfigLocalService tradeConfigLocalService;

    public static final String STATISTICS_INFO_KEY = "statistics_info";
    public static final String STATISTICS_INFO_NO_REFRESH_KEY = "statistics_info_no_refresh";
    public static final long STATISTICS_INFO_KEY_EXPIRE_TIME = 5;
    private static final String PLATFORM_START_DAY = "2014-09-01";

    public StatisticsInfoResponseDTO queryStatisticsInfo(){
        //从redis中获取统计数据信息
        Map<String,String> statisticsInfoMap = this.queryStatisticsInfoFromRedis();
        //如果未空，则从数据库中获取
        if(CollectionUtils.isEmpty(statisticsInfoMap)){
            statisticsInfoMap = this.queryStatisticsInfoFromDataBase();
        }

        String jsonString = JSON.toJSONString(statisticsInfoMap);
        StatisticsInfoResponseDTO statisticsInfoResponseDTO = JSON.parseObject(jsonString,StatisticsInfoResponseDTO.class);
        statisticsInfoResponseDTO.setOperateDays(this.getOperateDays());
        return statisticsInfoResponseDTO;
    }

    //获取平台安全运营时间
    private String getOperateDays(){
        long platformOnline = 0l;
        try {
            //平台运营时间
            Date startDate = FastDateFormat.getInstance("yyyy-MM-dd").parse(PLATFORM_START_DAY);
            platformOnline = DateUtils.daysBetween(startDate, new Date());
        } catch (ParseException e) {
            log.error("getOperateDays error",e);
        }
        return String.valueOf(platformOnline);
    }

    private Map<String,String> queryStatisticsInfoFromRedis(){
        Map<String,String> statisticsInfoMap = null;
        try {
            String noRefreshFlag = redisTemplate.opsForValue().get(STATISTICS_INFO_NO_REFRESH_KEY);
            if(noRefreshFlag==null){//如果“无需刷新标记”不存在，则说明数据已经过期，需要重新刷新数据
                return null;
            }
            HashOperations<String,String,String> hashOperations = redisTemplate.opsForHash();
            statisticsInfoMap = hashOperations.entries(STATISTICS_INFO_KEY);
            log.info("queryStatisticsInfoFromRedis.statisticsInfoMap={}",JSON.toJSONString(statisticsInfoMap));
        } catch (Exception e) {
            log.info("queryStatisticsInfoFromRedis error",e);
        }
        return statisticsInfoMap;
    }

    private Map<String,String> queryStatisticsInfoFromDataBase(){
        log.info("queryStatisticsInfoFromDataBase start");
        /*Map<String,String> statisticsInfoMap = this.queryStatisticsInfoFromRedis();
        if(!CollectionUtils.isEmpty(statisticsInfoMap)){
            return statisticsInfoMap;
        }*/
        Map<String,String> statisticsInfoMap = new HashMap<>();
        statisticsInfoMap.put(StatisticsTypeEnum.REGISTER_USER_COUNT.getStatisticsFieldName(),this.getStatisticsInfoValue(StatisticsTypeEnum.REGISTER_USER_COUNT));
        statisticsInfoMap.put(StatisticsTypeEnum.APPLY_LOAN_USER_COUNT.getStatisticsFieldName(),this.getStatisticsInfoValue(StatisticsTypeEnum.APPLY_LOAN_USER_COUNT));
        statisticsInfoMap.put(StatisticsTypeEnum.TODAY_REGISTER_USER_COUNT.getStatisticsFieldName(),this.getStatisticsInfoValue(StatisticsTypeEnum.TODAY_REGISTER_USER_COUNT));
        statisticsInfoMap.put(StatisticsTypeEnum.CUMULATIVE_TRADE_AMOUNT.getStatisticsFieldName(),this.getStatisticsInfoValue(StatisticsTypeEnum.CUMULATIVE_TRADE_AMOUNT));
        statisticsInfoMap.put(StatisticsTypeEnum.APPLY_LOAN_AMOUNT.getStatisticsFieldName(),this.getStatisticsInfoValue(StatisticsTypeEnum.APPLY_LOAN_AMOUNT));
        statisticsInfoMap.put(StatisticsTypeEnum.CUMULATIVE_USER_PROFIT.getStatisticsFieldName(),this.getStatisticsInfoValue(StatisticsTypeEnum.CUMULATIVE_USER_PROFIT));
        log.info("queryStatisticsInfoFromDataBase.statisticsInfoMap={}",JSON.toJSONString(statisticsInfoMap));
        //将统计数据信息放入redis缓存中
        this.putStatisticsInfoInfoRedis(statisticsInfoMap);
        return statisticsInfoMap;
    }

    private void putStatisticsInfoInfoRedis(Map<String,String> statisticsInfoMap){
        log.info("putStatisticsInfoInfoRedis start");
        try {
            redisTemplate.opsForHash().putAll(STATISTICS_INFO_KEY,statisticsInfoMap);
            redisTemplate.expire(STATISTICS_INFO_KEY, STATISTICS_INFO_KEY_EXPIRE_TIME, TimeUnit.MINUTES);
            redisTemplate.opsForValue().set(STATISTICS_INFO_NO_REFRESH_KEY,"noRefresh", STATISTICS_INFO_KEY_EXPIRE_TIME, TimeUnit.MINUTES);
            log.info("putStatisticsInfoInfoRedis success");
        } catch (Exception e) {
            log.info("putStatisticsInfoInfoRedis error",e);
        }
    }

    private String getStatisticsInfoValue(StatisticsTypeEnum statisticsTypeEnum){
        BigDecimal value = this.getStatisticsInitialValue(statisticsTypeEnum);
        try {
            StatisticsInfo statisticsInfo = statisticsInfoMapper.queryStatisticsInfoByStatisticsTypeEnum(statisticsTypeEnum);
            if(statisticsInfo!=null){
                BigDecimal statisticsValue = statisticsInfo.getStatisticsValue();
                value = (statisticsValue==null?value:value.add(statisticsValue));
            }
        } catch (Exception e) {
            log.error("getStatisticsInfoValue异常,statisticsTypeEnum={}",JSON.toJSONString(statisticsTypeEnum));
        }
        return value.toString();
    }

    private BigDecimal getStatisticsInitialValue(StatisticsTypeEnum statisticsTypeEnum){
        BigDecimal initialValue = BigDecimal.ZERO;
        try {
            String configValue = tradeConfigLocalService.selectTradeConfigByEmun(statisticsTypeEnum.getInitialStatisticsEnum());
            if(StringUtils.hasText(configValue)){
                initialValue = new BigDecimal(configValue);
            }
        } catch (Exception e) {
            log.error("getStatisticsInitialValue异常,statisticsTypeEnum={}",JSON.toJSONString(statisticsTypeEnum));
        }
        return initialValue;
    }

    /**
     * 获取当天剩余秒数
     */
    private long getLeftSecondsToday() {
        LocalDate now = new LocalDate();
        return new Duration(now.toDateTimeAtCurrentTime(), now.plusDays(1).toDateTimeAtStartOfDay()).getStandardSeconds();
    }

    //获取借款成功金额-累计交易金额：成功满标的合同金额
    private BigDecimal statisticsCumulativeTradeAmount(){
        return projectMapperExt.statisticsLoanAmountByStatusAndSubStatus(Arrays.asList(ProjectStatusEnum.REPAYING,ProjectStatusEnum.FINISH),null);
    }

    //获取申请借款金额-提交借款申请的合同金额：包括：系统拒绝的、人工审核通过的、人工审核退回的、审核不通过的、提交到后台用户自己取消借款的  等多个状态
    private BigDecimal statisticsApplyLoanAmount(){
        return projectMapperExt.statisticsLoanAmountByStatusAndSubStatus(null,null);
    }

    /**
     *保存累计交易金额-成功满标的合同金额
     */
    public void saveCumulativeTradeAmount(){
        try {
            BigDecimal cumulativeTradeAmount = this.statisticsCumulativeTradeAmount();
            log.info("saveCumulativeTradeAmount.cumulativeTradeAmount={}",cumulativeTradeAmount);
            int saveCount = saveStatisticsInfo(StatisticsTypeEnum.CUMULATIVE_TRADE_AMOUNT,cumulativeTradeAmount);
            log.info("saveCumulativeTradeAmount.cumulativeTradeAmount={},saveCount={}",cumulativeTradeAmount,saveCount);
        } catch (Exception e) {
            log.error("saveCumulativeTradeAmount error",e);
        }
    }

    /**
     *保存申请借款金额
     */
    public void saveApplyLoanAmount(){
        try {
            BigDecimal applyLoanAmount = this.statisticsApplyLoanAmount();
            log.info("saveApplyLoanAmount.applyLoanAmount={}",applyLoanAmount);
            int saveCount = saveStatisticsInfo(StatisticsTypeEnum.APPLY_LOAN_AMOUNT,applyLoanAmount);
            log.info("saveApplyLoanAmount.applyLoanAmount={},saveCount={}",applyLoanAmount,saveCount);
        } catch (Exception e) {
            log.error("saveApplyLoanAmount error",e);
        }
    }

    /**
     *保存总收益
     */
    public void saveCumulativeUserProfit(BigDecimal cumulativeUserProfit){
        try {
            log.info("saveCumulativeUserProfit.cumulativeUserProfit={}",cumulativeUserProfit);
            int saveCount = saveStatisticsInfo(StatisticsTypeEnum.CUMULATIVE_USER_PROFIT,cumulativeUserProfit);
            log.info("saveCumulativeUserProfit.cumulativeUserProfit={},saveCount={}",cumulativeUserProfit,saveCount);
        } catch (Exception e) {
            log.error("saveCumulativeUserProfit error",e);
        }
    }



    public int saveStatisticsInfo(StatisticsTypeEnum statisticsTypeEnum, BigDecimal statisticsValue){
        Date now = new Date();
        StatisticsInfo oldStatisticsInfo = statisticsInfoMapper.queryStatisticsInfoByStatisticsTypeEnum(statisticsTypeEnum);
        log.info("saveStatisticsInfo.oldStatisticsInfo={}", JSON.toJSONString(oldStatisticsInfo));
        StatisticsInfo newStatisticsInfo = new StatisticsInfo();
        newStatisticsInfo.setStatisticsType(statisticsTypeEnum.getStatisticsType());
        newStatisticsInfo.setStatisticsValue(statisticsValue);
        newStatisticsInfo.setUpdateTime(now);
        if(oldStatisticsInfo==null){
            newStatisticsInfo.setId(snowflakeIdWorker.nextId());
            newStatisticsInfo.setDescription(statisticsTypeEnum.getStatisticsTypeDesc());
            newStatisticsInfo.setCreateTime(now);
            return statisticsInfoMapper.insertSelective(newStatisticsInfo);
        }else{
            newStatisticsInfo.setId(oldStatisticsInfo.getId());
            return statisticsInfoMapper.updateByPrimaryKeySelective(newStatisticsInfo);
        }
    }
}
